//08290016
#include "ctcpserver.hpp"

bool ctcpserver::initserver(const unsigned short in_port) {
    //第1步：创建服务端的socket。
    if ((m_listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        return false;
    m_port = in_port; 
    //第2步：把服务端用于通信的IP和端口绑定到socket上。
    struct sockaddr_in servaddr;
    //用于存放服务端P和端口的数据结构。
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    //指定协议 
    servaddr.sin_port = htons(m_port); // 指定通信端口，普通用户只能用1024以上的端口。
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 服务端任意网卡的IP都可以用于通讯。
    //绑定服务端的IP和端口。
    //端口复用 避免出现 address already is use
    // int opt_val = 1;
    // setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, (const void*)&opt_val, sizeof(opt_val));
    if (bind(m_listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {
        close(m_listenfd);
        m_listenfd = -1;
        return false;
    }
    if (listen(m_listenfd, 5) == -1) {
        // perror("listen");
        close(m_listenfd);
        m_listenfd = -1;
        return false;
    }
    return true;
}
bool ctcpserver::accept()
{
    struct sockaddr_in caddr;
    // 客户端的地址信息。
    socklen_t addrlen = sizeof(caddr);
    //struct sockaddr._in的大小。
    if ((m_clientfd = ::accept(m_listenfd, (struct sockaddr*)&caddr, &addrlen)) == -1)
        return false;
    m_clientip = inet_ntoa(caddr.sin_addr);//把客户端的地址从大端序转换成字符串。
    return true;
}
const string & ctcpserver::clientip( ) const{
        return m_clientip;
    }
    //向对端发送报文，成功返回true,失败返回false。
bool ctcpserver::send(const string& buffer) {
    if (m_clientfd == -1)return false;
    if ((::send(m_clientfd, buffer.data(), buffer.size(),0))<=0)
        return false;
    return true;
}


    //接收对端的报文，成功返回true,
    //失败返回false。
    //buffer-存放接收到的报文的内容，max en-本次接收报文的最大长度。

bool ctcpserver::recv(string& buffer, const size_t maxlen) {
        buffer.clear();
        // 清空容器。
        buffer.resize(maxlen);//设置容器的大小为maxlen。
        int readn = ::recv(m_clientfd, &buffer[0], buffer.size(), 0); // 直接操作buffer的内存。
        if (readn <= 0) {
            buffer.clear();
            return false;
        }
        buffer.resize(readn);// 重置buffer的实际大小。
        return true;
}
//关闭监听的socket。
bool ctcpserver::closelisten (){
        if (m_listenfd==-1)
            return false;
        ::close (m_listenfd);
        m_listenfd = -1;
        return true;
    }
    //关闭客户端连上来的socket。
bool ctcpserver::closeclient ()
{
    if (m_clientfd==-1)
        return false;
    ::close (m_clientfd);
    m_clientfd=-1;
    return true;
}

int sendString(const string& buffer,int fd){
    cout<<buffer<<endl;
    if (fd == -1)
        return -1;
    if ((::send(fd, buffer.data(), buffer.size(), 0)) <= 0)
        return -1;
    return 0;
}

int sendPackage(const string& buffer,const uint16_t cmd,int fd){
    printf("recv:0x%x \n", cmd);
    cout<<buffer<<endl;
    if (fd == -1)
        return -1;
    string pks;
    pks.resize(5);
    pks[0] = 0x5A;
    pks[1] = (cmd >> 8) & 0xFF;
    pks[2] =  cmd & 0xFF;
    pks[3] = (((uint16_t)buffer.size()) >> 8) & 0xFF;
    pks[4] = ((uint16_t)buffer.size()) & 0xFF;
    pks.append(buffer);
    pks.push_back(0xA5);
    if ((::send(fd, pks.data(), pks.size(), 0)) <= 0)
        return -1;
    return 0;
}

string GetValidData(string recvData, int totalSize) {
    for (int i = 0;i < totalSize;i++) {
        if ((recvData[i] == 0x5A))
        {
            uint16_t dataLength = ((((uint16_t)recvData[i + 3]) << 8) & 0xFF00) + (((uint16_t)recvData[i + 4]) & 0x00FF);
            // printf("dataLength:%d\n",dataLength);
            // printf("%d\n",recvData[i + 5 + dataLength]);
            if (i + 6 + dataLength > totalSize)
                continue;
            else if ((uint8_t)recvData[i + 5 + dataLength] == 0xA5) {
                // printf("here\n");
                return recvData.substr(i, 6 + dataLength);
            }
        }
    }
    return "";
}
